﻿using System;
using System.Diagnostics;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using System.Configuration;
using System.IO;

namespace mki.Backup.Helper
{
	/// <summary>
	/// Logging class
	/// </summary>
	public class Logging
	{
		#region Fields (2)

		private static LoggingSettings curLoggingSettings = null;
		private static String logFileNameAndPath = null;

		#endregion Fields

		#region Enums (1)

		internal enum LogLevel
		{
			Critical = 0,
			Error = 1,
			Warning = 2,
			Debug = 3,
			Information = 4,
			Verbose = 5
		}

		#endregion Enums

		#region Properties (3)

		/// <summary>
		/// Gets or sets the log file path.
		/// </summary>
		/// <value>
		/// The log file path.
		/// </value>
		public static String LogFilePath
		{
			get
			{
				String logFilePath = String.Empty;
				if (String.IsNullOrWhiteSpace(logFileNameAndPath))
				{
					// get the first listener when its type is RollingFlatFileTraceListenerData
					var loggerCollection = loggingSettings.TraceListeners;
					if (loggerCollection != null && loggerCollection.Count > 0)
					{
						var rollingFlatFileLogger = loggerCollection.Get(0) as RollingFlatFileTraceListenerData;
						if (rollingFlatFileLogger != null)
						{
							logFilePath = rollingFlatFileLogger.FileName;
						}
					}
				}
				else
				{
					logFilePath = logFileNameAndPath;
				}
				return logFilePath;
			}
			set
			{
				logFileNameAndPath = value;
			}
		}

		/// <summary>
		/// Gets the logging settings.
		/// </summary>
		/// <value>The logging settings.</value>
		private static LoggingSettings loggingSettings
		{
			get
			{
				if (curLoggingSettings == null)
				{
					try
					{
						if (ConfigurationManager.GetSection("loggingConfiguration").GetType() == typeof(LoggingSettings))
						{
							curLoggingSettings = (LoggingSettings)ConfigurationManager.GetSection("loggingConfiguration");
						}
					}
					catch (Exception ex)
					{
						if (Debugger.IsAttached)
						{
							Console.WriteLine(String.Format("{0}\n{1}", ex.Message, ex.StackTrace));
						}
					}
				}
				return curLoggingSettings;
			}
		}

		/// <summary>
		/// Gets the log path.
		/// </summary>
		public static String LogPath
		{
			get
			{
				String logPath = String.Empty;
				if (String.IsNullOrWhiteSpace(logFileNameAndPath))
				{
					// get the first listener when its type is RollingFlatFileTraceListenerData
					var loggerCollection = loggingSettings.TraceListeners;
					if (loggerCollection != null && loggerCollection.Count > 0)
					{
						var rollingFlatFileLogger = loggerCollection.Get(0) as RollingFlatFileTraceListenerData;
						if (rollingFlatFileLogger != null)
						{
							logPath = rollingFlatFileLogger.FileName;
						}
					}
				}
				else
				{
					logPath = logFileNameAndPath;
				}

				// extract path only
				if (!String.IsNullOrWhiteSpace(logPath))
				{
					try { logPath = Path.GetDirectoryName(logPath); }
					catch { logPath = String.Empty; }
				}

				return logPath;
			}
		}

		#endregion Properties

		#region Methods (13)

		// Public Methods (12) 

		/// <summary>
		/// Writes a critical message to logfile
		/// </summary>
		/// <param name="message"> (String) Message to write </param>
		public static void WriteCritical(String message)
		{
			WriteCritical(message, null);
		}

		/// <overloads>Supports formatting of message with params</overloads>
		/// <summary>
		/// Writes a critical message to logfile
		/// </summary>
		/// <param name="message"> (String) Message to write </param>
		/// <param name="arg0"> (object[]) Arguments for message </param>
		public static void WriteCritical(String message, params object[] arg0)
		{
			write(LogLevel.Critical, message, arg0);
		}

		/// <summary>
		/// Writes a debug message to logfile
		/// </summary>
		public static void WriteDebug(String message)
		{
			WriteDebug(message, null);
		}

		/// <overloads>Supports formatting of message with params</overloads>
		/// <summary>
		/// Writes a debug message to logfile
		/// </summary>
		/// <param name="message"> (String) Message to write </param>
		/// <param name="arg0"> (object[]) Arguments for message </param>
		public static void WriteDebug(String message, params object[] arg0)
		{
			write(LogLevel.Debug, message, arg0);
		}

		/// <summary>
		/// Writes a error message to logfile
		/// </summary>
		/// <param name="message"> (String) Message to write </param>
		public static void WriteError(String message)
		{
			WriteError(message, null);
		}

		/// <overloads>Supports formatting of message with params</overloads>
		/// <summary>
		/// Writes a error message to logfile
		/// </summary>
		/// <param name="message"> (String) Message to write </param>
		/// <param name="arg0"> (object[]) Arguments for message </param>
		public static void WriteError(String message, params object[] arg0)
		{
			write(LogLevel.Error, message, arg0);
		}

		/// <summary>
		/// Writes a information message to logfile
		/// </summary>
		/// <param name="message"> (String) Message to write </param>
		public static void WriteInformation(String message)
		{
			WriteInformation(message, null);
		}

		/// <overloads>Supports formatting of message with params</overloads>
		/// <summary>
		/// Writes a information message to logfile
		/// </summary>
		/// <param name="message"> (String) Message to write </param>
		/// <param name="arg0"> (object[]) Arguments for message </param>
		public static void WriteInformation(String message, params object[] arg0)
		{
			write(LogLevel.Information, message, arg0);
		}

		/// <summary>
		/// Writes a verbose message to logfile
		/// </summary>
		/// <param name="message"> (String) Message to write </param>
		public static void WriteVerbose(String message)
		{
			WriteVerbose(message, null);
		}

		/// <overloads>Supports formatting of message with params</overloads>
		/// <summary>
		/// Writes a verbose message to logfile
		/// </summary>
		/// <param name="message"> (String) Message to write </param>
		/// <param name="arg0"> (object[]) Arguments for message </param>
		public static void WriteVerbose(String message, params object[] arg0)
		{
			write(LogLevel.Verbose, message, arg0);
		}

		/// <summary>
		/// Writes a warning message to logfile
		/// </summary>
		/// <param name="message"> (String) Message to write </param>
		public static void WriteWarning(String message)
		{
			WriteWarning(message, null);
		}

		/// <overloads>Supports formatting of message with params</overloads>
		/// <summary>
		/// Writes a warning message to logfile
		/// </summary>
		/// <param name="message"> (String) Message to write </param>
		/// <param name="arg0"> (object[]) Arguments for message </param>
		public static void WriteWarning(String message, params object[] arg0)
		{
			write(LogLevel.Warning, message, arg0);
		}
		// Private Methods (1) 

		/// <summary>
		/// Writes the specified level.
		/// </summary>
		/// <param name="level">The level.</param>
		/// <param name="message">The message.</param>
		/// <param name="arg0">The arg0.</param>
		private static void write(LogLevel level, String message, params object[] arg0)
		{
			try
			{	// add params to message
				if (arg0 != null) { message = String.Format(message, arg0); }

				if (!String.IsNullOrWhiteSpace(logFileNameAndPath))
				{ // logging with overwritten output file
					try
					{
						CustomLogger.Write(logFileNameAndPath, message, level.ToString());
					}
					catch (Exception ex)
					{
						if (Debugger.IsAttached)
						{
							Console.WriteLine("{0}\n{1}", ex.Message, ex.StackTrace);
						}
						// log normally
						Logger.Write(String.Format("{0}: {1}", level.ToString().ToUpper(), message), level.ToString());
					}
				}
				else
				{	// normal logging complete configured via app.config
					CustomLogger.Dispose();
					Logger.Write(String.Format("{0}: {1}", level.ToString().ToUpper(), message), level.ToString());
				}
			}
			catch (Exception ex)
			{
				if (Debugger.IsAttached) { Console.WriteLine("{0}\n{1}", ex.Message, ex.StackTrace); }
			}
		}

		#endregion Methods
	}
}